package me.yxy.mobanddd.domain.transportorder;

import com.fasterxml.jackson.annotation.JsonIgnoreProperties;
import lombok.Getter;
import lombok.Setter;
import me.yxy.mobanddd.components.AppContext;
import me.yxy.mobanddd.controller.request.command.ModifyTransportRequest;
import me.yxy.mobanddd.domain.domainservice.LocatingReceiverService;
import me.yxy.mobanddd.domain.events.TransportOrderModifiedEvent;
import me.yxy.mobanddd.domain.shipment.Shipment;
import me.yxy.mobanddd.domain.warehouse.Warehouse;
import me.yxy.mobanddd.domain.warehouse.WarehouseRepository;
import me.yxy.mobanddd.exception.BusinessException;

import javax.persistence.*;
import java.util.Date;
import java.util.Optional;


@Setter
@Getter
@Entity
@Table(name = "t_transport_order")
@JsonIgnoreProperties(value = { "hibernateLazyInitializer", "handler" })
public class TransportOrder {

    @Id
    @GeneratedValue(strategy= GenerationType.IDENTITY)
    private Long id;

    private String receiverName;

    private String receiverTel;

    private String receiverLocation;

    private String code;

    private Double receiveLongitude;

    private Double receiveLatitude;

    private Double distance;

    private Integer deliveryOrder;

    private Integer type;

    private Date createdTime;

    @Enumerated
    private TransportOrderStatus status;

    /**
     * 发货仓库
     */
    @Setter
    @ManyToOne(fetch = FetchType.LAZY)
    @JoinColumn(name = "warehouse_id")
    private Warehouse warehouse;

    /**
     * 所配载到的调度单
     */
    @Setter
    @ManyToOne(fetch = FetchType.LAZY)
    @JoinColumn(name = "shipment_id")
    private Shipment shipment;

    /**
     * 运单绑定调度单（或者说，配载到一个调度单中）
     * @param shipment
     */
    public void bindShipment(Shipment shipment) {
//        setShipment(shipment);
//        transportOrderRepository.save(this);

        //广播消息出去
//        eventPublisher.publishEvent(new TransportOrderBindShipmentEvent(this,shipment.getId(),this.id));
//        EventPublisher.publish(new TransportOrderBindShipmentEvent(this,shipment.getId(),this.id));
    }

    protected TransportOrder() {
    }

    /**
     * 修改运单基本信息
     * @param request
     */
    public void modifyBrief(ModifyTransportRequest request) {

        this.setReceiverName(request.getReceiverName());

        //是否真的要修改地址？
        if(!request.getReceiverLocation().equals(this.getReceiverLocation())){

            //调用地理位置分析服务来处理
            LocatingReceiverService.LocatingResult result = AppContext.bean(LocatingReceiverService.class).process(request.getReceiverLocation());
            this.setReceiverLocation(request.getReceiverLocation());
            this.setReceiveLongitude(result.getLongitude());
            this.setReceiveLatitude(result.getLatitude());
        }



        //检查仓库是否有变化
        if(needChangeWarehouse(request.getWarehouseId())){

            //TODO 这里业务其实跨领域了，所以其实可以挪到领域服务中的
            Optional<Warehouse> warehouse = AppContext.bean(WarehouseRepository.class).findById(request.getWarehouseId());
            this.setWarehouse(warehouse.orElseThrow(()->new BusinessException("所选仓库不存在异常")));
        }

        /*
            关于事件什么时候发布?
         */
        AppContext.eventMachine().publish(new TransportOrderModifiedEvent(this,request.getTransportId()));

    }

    private boolean needChangeWarehouse(Long newWarehouseId) {

        //如果为空，则直接跳过，目前不允许解绑已绑定的仓库，所以null严格来说是异常
        if(newWarehouseId==null){
            return false;
        }

        return !newWarehouseId.equals(this.getWarehouse().getId());
    }

    /**
     * 保存运单在调度单中的配送顺序
     * @param deliveryOrder
     */
    public void saveDeliveryOrder(int deliveryOrder) {
        this.setDeliveryOrder(deliveryOrder);
    }

    public void remove() {
        AppContext.bean(TransportOrderRepository.class).delete(this);

        //TODO 是否需要广播消息？这个完全看业务需求，如果目前没有任何后置业务流程，那么就没必要去为了发消息而发消息
    }
}
